package com.mspbots.web.security;

import com.mspbots.web.params.ChangPasswordRequest;
import com.mspbots.web.params.UserParam;
import com.mspbots.web.security.service.AuthService;
import com.mspbots.web.security.service.UsersService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.http.CacheControl;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebSession;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import static com.mspbots.web.security.service.AuthService.DEFAULT_TENANT_ADMIN_ROLE_NAME;
import static com.mspbots.web.security.service.AuthService.DEFAULT_TENANT_USER_ROLE_NAME;

/**
 * com.mspbots.web.security.AuthController
 *
 * @author Alex bob(https://github.com/vnobo)
 * @date Created by 2019/6/24
 */
@Log4j2
@RestController
@RequiredArgsConstructor
public class AuthController {

    private final AuthService authService;
    private final UsersService usersService;

    @GetMapping(path = "oauth")
    public Mono<ResponseEntity<OauthResult>> oauth(AbstractAuthenticationToken principal, WebSession webSession) {
        return this.authService.oauth(principal.getName())
                .map(result -> {
                    result.setToken(webSession.getId());
                    return result;
                })
                .map(result -> ResponseEntity.ok().cacheControl(CacheControl.maxAge(30, TimeUnit.MINUTES))
                        .body(result));
    }

    @GetMapping(path = "/sso/teams/{teamsId}")
    public Mono<OauthResult> ssoTeamsLogin(@PathVariable String teamsId, @RequestParam String email, ServerWebExchange exchange) {
        return this.authService.teamsLogin(teamsId, email, exchange);
    }

    @PostMapping(path = "chang-password")
    public Mono changPassword(@RequestBody ChangPasswordRequest requestParams) {
        Assert.notNull(requestParams.getPassword(), () -> "The current password cannot be empty.");
        Assert.notNull(requestParams.getNewPassword(), () -> "The newPassword cannot be empty.");
        return this.usersService.changePassword(requestParams)
                .cache(Duration.ofMinutes(30));
    }

    @PostMapping(path = "register")
    public Mono register(@RequestBody UserParam request) {
        request.setRoles(Set.of(DEFAULT_TENANT_ADMIN_ROLE_NAME, DEFAULT_TENANT_USER_ROLE_NAME));
        return this.usersService.register(request);
    }


    @PostMapping(path = "change/user")
    public Mono changeUser(@RequestBody UserParam request) {
        return this.usersService.changeUser(request);
    }

}
